#import "StLivenessDetectorPlugin.h"

#import "STSilentLivenessController.h"
#import "STSilentLivenessResultViewController.h"
#import "STSilentLivenessCommon.h"
#import "UIView+EX.h"

@interface StLivenessDetectorPlugin ()<STSilentLivenessControllerDelegate, STSilentLivenessDetectorDelegate>

@property (nonatomic, weak) STSilentLivenessController *livenessVC;
@property (nonatomic, strong) UIView *progressHUD;
@property (nonatomic, strong) UILabel *textlabel;
@property (nonatomic, strong) NSString *messageStr;

@end

@implementation StLivenessDetectorPlugin {
    FlutterResult _detectResult;
}

static UIViewController *viewController;

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    viewController = UIApplication.sharedApplication.delegate.window.rootViewController;
    FlutterMethodChannel* channel = [FlutterMethodChannel
        methodChannelWithName:@"st_liveness_detector"
              binaryMessenger:[registrar messenger]];
    StLivenessDetectorPlugin* instance = [[StLivenessDetectorPlugin alloc] init];
    [registrar addMethodCallDelegate:instance channel:channel];
}



- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  if ([@"startDetect" isEqualToString:call.method]) {
      _detectResult = result;
      
      NSString *mediaType = AVMediaTypeVideo;
      AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
      if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) {
          [self showProgressHUD:@"相机权限获取失败:请在设置-隐私-相机中开启后重试"];
          return;
      }
            
      STSilentLivenessController *livenessVC = [[STSilentLivenessController alloc] initWithSetDelegate:self];
      [livenessVC.detector setBrowOcclusionEnable:NO];

      self.livenessVC = livenessVC;
      UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.livenessVC];
      nav.modalPresentationStyle = UIModalPresentationFullScreen;

      [viewController presentViewController:nav animated:YES completion:nil];
      
  } else {
      result(FlutterMethodNotImplemented);
  }
}

#pragma - mark -
#pragma - mark STLivenessDetectorDelegate

- (NSString *)messageStringByCloudInternalCode:(STIDSilentLivenessCloudInternalCode)cloudInternalCode {
    NSString *messageString = @"";
    switch (cloudInternalCode) {
        case STIDSilentLiveness_CLOUD_UNKNOWN_CODE: {
            messageString = @"云端返回未知错误";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_DEFAULT: {
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_SUCCESS: {
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_API_KEY_MISSING: {
            messageString = @"api_key值为空";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_INVALID_API_KEY: {
            messageString = @"无效的api_key";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_API_KEY_IS_DISABLED: {
            messageString = @"api_key被禁用";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_API_KEY_HAS_EXPIRED: {
            messageString = @"api_key已过期 ";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_PERMISSION_DENIED: {
            messageString = @"无该功能权限";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_BUNDLE_ID_MISSING: {
            messageString = @"bundle_id值为空";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_BUNDLE_ID_IS_DISABLED: {
            messageString = @"bundle_id被禁用";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_DAILY_RATE_LIMIT_EXCEEDED: {
            messageString = @"每日调用已达限制";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_APP_SIGN_MISSING: {
            messageString = @"未传入应用签名";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_INVALID_APP_SIGN: {
            messageString = @"应用签名验证失败";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_INVALID_SIGNATURE: {
            messageString = @"数据一致性验证失败";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_INVALID_BUNDLE_ID: {
            messageString = @"bundle_id验证失败";
            break;
        }
        case STIDSilentLiveness_CLOUD_INTERNAL_SENSETIME_ERROR: {
            messageString = @"内部错误，请联系商汤支持人员";
            break;
        }
    }
    return messageString;
}

- (NSString *)messageStringByLivenessResult:(STIDSilentLivenessResult)livenessResult {
    NSString *messageString = @"";
    NSString *description = @"";
    switch (livenessResult) {
        case STIDSilentLiveness_OK: {
            break;
        }

        case STIDSilentLiveness_E_LICENSE_INVALID: {
            messageString = @"未通过授权验证";
            description = @"STIDSilentLiveness_E_LICENSE_INVALID";
            break;
        }

        case STIDSilentLiveness_E_LICENSE_FILE_NOT_FOUND: {
            messageString = @"授权文件不存在";
            description = @"STIDSilentLiveness_E_LICENSE_FILE_NOT_FOUND";
            break;
        }

        case STIDSilentLiveness_E_LICENSE_BUNDLE_ID_INVALID: {
            messageString = @"绑定包名错误";
            description = @"STIDSilentLiveness_E_LICENSE_BUNDLE_ID_INVALID";
            break;
        }

        case STIDSilentLiveness_E_LICENSE_EXPIRE: {
            messageString = @"授权文件过期";
            description = @"STIDSilentLiveness_E_LICENSE_EXPIRE";
            break;
        }

        case STIDSilentLiveness_E_LICENSE_VERSION_MISMATCH: {
            messageString = @"License与SDK版本不匹";
            description = @"STIDSilentLiveness_E_LICENSE_VERSION_MISMATCH";
            break;
        }

        case STIDSilentLiveness_E_LICENSE_PLATFORM_NOT_SUPPORTED: {
            messageString = @"License不支持当前平台";
            description = @"STIDSilentLiveness_E_LICENSE_PLATFORM_NOT_SUPPORTED";
            break;
        }

        case STIDSilentLiveness_E_MODEL_INVALID: {
            messageString = @"模型文件错误";
            description = @"STIDSilentLiveness_E_MODEL_INVALID";
            break;
        }

        case STIDSilentLiveness_E_DETECTION_MODEL_FILE_NOT_FOUND: {
            messageString = @"DETECTION 模型文件不存在";
            description = @"STIDSilentLiveness_E_DETECTION_MODEL_FILE_NOT_FOUND";
            break;
        }

        case STIDSilentLiveness_E_ALIGNMENT_MODEL_FILE_NOT_FOUND: {
            messageString = @"ALIGNMENT 模型文件不存在";
            description = @"STIDSilentLiveness_E_ALIGNMENT_MODEL_FILE_NOT_FOUND";
            break;
        }

        case STIDSilentLiveness_E_FRAME_SELECTOR_MODEL_FILE_NOT_FOUND: {
            messageString = @"FRAME_SELECTOR 模型文件不存在";
            description = @"STIDSilentLiveness_E_FRAME_SELECTOR_MODEL_FILE_NOT_FOUND";
            break;
        }

        case STIDSilentLiveness_E_ANTI_SPOOFING_MODEL_FILE_NOT_FOUND: {
            messageString = @"ANTI_SPOOFING 模型文件不存在";
            description = @"STIDSilentLiveness_E_ANTI_SPOOFING_MODEL_FILE_NOT_FOUND";
            break;
        }

        case STIDSilentLiveness_E_FACE_QUALITY_MODEL_FILE_NOT_FOUND: {
            messageString = @"FACE_QUALITY 模型文件不存在";
            description = @"STIDSilentLiveness_E_FACE_QUALITY_MODEL_FILE_NOT_FOUND";
            break;
        }

        case STIDSilentLiveness_E_MODEL_EXPIRE: {
            messageString = @"模型文件过期";
            description = @"STIDSilentLiveness_E_MODEL_EXPIRE";
            break;
        }

        case STIDSilentLiveness_E_INVALID_ARGUMENT: {
            messageString = @"参数设置不合法";
            description = @"STIDSilentLiveness_E_INVALID_ARGUMENT";
            break;
        }

        case STIDSilentLiveness_E_CALL_API_IN_WRONG_STATE: {
            messageString = @"错误的方法状态调用";
            description = @"STIDSilentLiveness_E_CALL_API_IN_WRONG_STATE";
            break;
        }

        case STIDSilentLiveness_E_CAPABILITY_NOT_SUPPORTED: {
            messageString = @"授权文件能力不支持";
            description = @"STIDSilentLiveness_E_CAPABILITY_NOT_SUPPORTED";
            break;
        }

        case STIDSilentLiveness_E_API_KEY_INVALID: {
            messageString = @"API_KEY或API_SECRET无效";
            description = @"STIDSilentLiveness_E_API_KEY_INVALID";
            break;
        }

        case STIDSilentLiveness_E_SERVER_ACCESS: {
            messageString = @"服务器访问错误";
            description = @"STIDSilentLiveness_E_SERVER_ACCESS";
            break;
        }

        case STIDSilentLiveness_E_SERVER_TIMEOUT: {
            messageString = @"网络连接超时，请查看网络设置，重试一次";
            description = @"STIDSilentLiveness_E_SERVER_TIMEOUT";
            break;
        }

        case STIDSilentLiveness_E_HACK: {
            messageString = @"活体检测失败";
            description = @"STIDSilentLiveness_E_HACK";
            break;
        }

        case STIDSilentLiveness_E_TIMEOUT: {
            messageString = @"活体检测超时";
            description = @"STIDSilentLiveness_E_TIMEOUT";
            break;
        }
    }

    if (messageString.length > 0 && description.length > 0) {
        messageString = [NSString stringWithFormat:@"ResultCode: %@ \n %@", description, messageString];
    }
    return messageString;
}

- (void)dealWithErrorCode:(STIDSilentLivenessResult)livenessResult
             protobufData:(NSData *)protobufData
                   images:(NSArray *)imageArr
                faceRects:(NSArray *)faceRectArr {
//    if (protobufData.length > 0) {
//        [self saveProtobufData:protobufData images:imageArr];
//    }

    NSMutableArray *livenessImageArr = [NSMutableArray array];
    for (STSilentLivenessImage *image in imageArr) {
        [livenessImageArr addObject:image.image];
    }

    UIImage *faceImage = nil;
    STSilentLivenessRect *rect = faceRectArr.firstObject;
    if (rect != nil) {
        CGFloat faceWidth = rect.right - rect.left;
        CGFloat faceHeight = rect.bottom - rect.top;

        faceImage = [self cutCenterImage:livenessImageArr.firstObject
                                    left:rect.left
                                     top:rect.top
                                   width:faceWidth
                                  height:faceHeight];
    }

    if (STIDSilentLiveness_E_API_KEY_INVALID == livenessResult ||
        STIDSilentLiveness_E_SERVER_ACCESS == livenessResult || STIDSilentLiveness_E_SERVER_TIMEOUT == livenessResult ||
        STIDSilentLiveness_E_TIMEOUT == livenessResult || STIDSilentLiveness_E_HACK == livenessResult) {
        [self showLivenessResultString:self.messageStr livenessImage:livenessImageArr.firstObject faceImage:faceImage];
    } else {
        [self showProgressHUD:self.messageStr];
        [viewController dismissViewControllerAnimated:YES completion:nil];
    }
}


- (void)silentLivenessSuccessWithProtobufData:(NSData *)protobufData
                                       images:(NSArray *)imageArr
                                    faceRects:(NSArray *)faceRectArr {
    // 注意,在您的app中千万不要这么做,这里是保存在 app/Documents
    // 目录下用来离线校验文件内容,在实际场景中应该直接将该数据上传.
    if (protobufData.length > 0) {
//        [self saveProtobufData:protobufData images:imageArr];
        // 取出每个阶段的图片
        NSMutableArray *livenessImageArr = [NSMutableArray array];

        for (STSilentLivenessImage *image in imageArr) {
            [livenessImageArr addObject:image.image];
        }
        CGFloat faceWidth;

        CGFloat faceHeight;

        STSilentLivenessRect *rect = faceRectArr.firstObject;
        faceWidth = rect.right - rect.left;
        faceHeight = rect.bottom - rect.top;

        UIImage *faceImage = [self cutCenterImage:livenessImageArr.firstObject
                                             left:rect.left
                                              top:rect.top
                                            width:faceWidth
                                           height:faceHeight];

        [self showLivenessResultString:@"" livenessImage:livenessImageArr.firstObject faceImage:faceImage];
    }
}

- (void)silentLivenessFailureWithErrorCode:(STIDSilentLivenessResult)livenessResult
                              protobufData:(NSData *)protobufData
                                    images:(NSArray *)imageArr
                                 faceRects:(NSArray *)faceRectArr {
    NSString *livenessResultErrorStr = [self messageStringByLivenessResult:livenessResult];
    self.messageStr = livenessResultErrorStr;
    [self dealWithErrorCode:livenessResult protobufData:protobufData images:imageArr faceRects:faceRectArr];
}

- (void)cancelDetect {
    [viewController dismissViewControllerAnimated:YES completion:nil];
}

- (void)silentLivenessVideoFrameRate:(NSInteger)rate {
    // printf("%d FPS\n",rate);
}
#pragma mark - STSilentLivenessControllerDelegate
- (void)silentLivenessControllerDeveiceError:(STIDSilentLivenessDeveiceError)deveiceError {
    switch (deveiceError) {
        case STIDSilentLiveness_E_CAMERA:
            self.messageStr = @"相机权限获取失败:请在设置-隐私-相机中开启后重试";

            break;

        case STIDSilentLiveness_WILL_RESIGN_ACTIVE:
            self.messageStr = @"活体检测已取消";

            break;
    }
    [self showProgressHUD:self.messageStr];
    [viewController dismissViewControllerAnimated:YES completion:nil];
}

- (UIImage *)cutCenterImage:(UIImage *)image
                       left:(NSInteger)left
                        top:(NSInteger)top
                      width:(NSInteger)width
                     height:(NSInteger)height {
    // 如果需要调整人脸裁剪结果的尺寸，请参考以下注释的代码
    //    CGFloat scaleValue = 2;
    //    left = left - (width / scaleValue);
    //    top = top - (height / scaleValue);
    //    width = scaleValue * width;
    //    height = scaleValue * height;

    if (left < 0) {
        left = 0;
    }
    if (top < 0) {
        top = 0;
    }
    CGRect rect = CGRectMake(left, top, width, height);

    CGImageRef imageRef = image.CGImage;
    CGImageRef imageRefRect = CGImageCreateWithImageInRect(imageRef, rect);
    UIImage *cutImage = [UIImage imageWithCGImage:imageRefRect];
    CGImageRelease(imageRefRect);

    return cutImage;
}
- (void)showLivenessResultString:(NSString *)resultString
                   livenessImage:(UIImage *)livenessImage
                       faceImage:(UIImage *)faceImage {
    
    NSData *imageData = UIImageJPEGRepresentation(livenessImage, 0.5);
        
    bool isSucceed = resultString.length <= 0;
    
    _detectResult(@{
        @"success": @(isSucceed),
        @"message": resultString,
        @"data": [FlutterStandardTypedData typedDataWithBytes: isSucceed ? imageData : [NSData data]],
    });
    
    _detectResult = nil;
    [viewController dismissViewControllerAnimated:YES completion:nil];
    
    
    
    //NSString *sbPath = [[NSBundle mainBundle] pathForResource:@"SenseID_Liveness_Silent" ofType:@"lic"];
    /*
    UIStoryboard *story = [UIStoryboard storyboardWithName:@"STView" bundle:nil];
    STSilentLivenessResultViewController *vc =
        [story instantiateViewControllerWithIdentifier:@"STSilentLivenessResultViewController"];

    if (resultString.length > 0) {
        vc.resultStr = resultString;
        vc.isSucceed = NO;
    } else {
        vc.isSucceed = YES;
    }
    vc.livenessImage = livenessImage;
    vc.faceImage = faceImage;

    [viewController dismissViewControllerAnimated:YES completion:nil];
    
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
    nav.modalPresentationStyle = UIModalPresentationFullScreen;
    
    [viewController presentViewController:nav animated:YES completion:nil];
    
    */
}
/**
 保存数据到沙盒的方法

 @param protobufData protobufData
 @param imageArr 人脸图片数组
 */
/*
- (void)saveProtobufData:(NSData *)protobufData images:(NSArray *)imageArr {
    // 注意,在您的app中千万不要这么做,这里是保存在 app/Documents
    // 目录下用来离线校验文件内容,在实际场景中应根据实际情况选择处理回传数据
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *filePath = paths[0];

    [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];

    NSString *strFileName =
        [[NSString stringWithFormat:@"%@", @"silentlivenessResult"] stringByReplacingOccurrencesOfString:@"."
                                                                                              withString:@""];

    [[NSFileManager defaultManager] createFileAtPath:[NSString pathWithComponents:@[filePath, strFileName]]
                                            contents:protobufData
                                          attributes:nil];

    for (int i = 0; i < imageArr.count; i++) {
        STSilentLivenessImage *stImage = imageArr[i];

        NSString *imagePath = [NSString stringWithFormat:@"%@/silentlivenessImage%i.jpg", filePath, i];

        [UIImageJPEGRepresentation(stImage.image, 1.0) writeToFile:imagePath atomically:YES];
    }
}
 */

- (void)showProgressHUD:(NSString *)textStr {
    [self hideProgressHUD];
    UIEdgeInsets tipInsets = UIEdgeInsetsMake(15, 20, 15, 20);
    CGSize screenSize = [UIScreen mainScreen].bounds.size;

    NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:textStr];
    [attr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:14] range:NSMakeRange(0, textStr.length)];
    [attr addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, textStr.length)];

    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
    style.lineHeightMultiple = 1.2;
    style.alignment = NSTextAlignmentCenter;
    [attr addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, textStr.length)];

    CGSize size =
        [attr boundingRectWithSize:CGSizeMake(screenSize.width - 80 - tipInsets.left - tipInsets.right, CGFLOAT_MAX)
                           options:NSStringDrawingUsesLineFragmentOrigin
                           context:nil]
            .size;
    self.textlabel.attributedText = attr;
    self.textlabel.frame = CGRectMake(tipInsets.left, tipInsets.top, size.width, size.height);
    [self.progressHUD addSubview:self.textlabel];

    self.progressHUD.frame =
        CGRectMake(0, 0, size.width + tipInsets.left + tipInsets.right, size.height + tipInsets.top + tipInsets.bottom);
    self.progressHUD.center = CGPointMake(screenSize.width * 0.5, screenSize.height * 0.5);

    UIView *window = [UIApplication sharedApplication].keyWindow;
    [window addSubview:self.progressHUD];
    [self performSelector:@selector(hideProgressHUD) withObject:nil afterDelay:2];
}
- (void)hideProgressHUD {
    [self.progressHUD removeFromSuperview];
}

- (UILabel *)textlabel {
    if (!_textlabel) {
        _textlabel = [[UILabel alloc] init];
        _textlabel.textColor = [UIColor whiteColor];
        _textlabel.font = [UIFont systemFontOfSize:14];
        _textlabel.numberOfLines = 0;
        _textlabel.backgroundColor = [UIColor clearColor];
        _textlabel.textAlignment = NSTextAlignmentCenter;
    }
    return _textlabel;
}

- (UIView *)progressHUD {
    if (!_progressHUD) {
        _progressHUD = [[UIView alloc] init];
        _progressHUD.layer.cornerRadius = 5;
        _progressHUD.layer.masksToBounds = YES;
        _progressHUD.backgroundColor = [UIColor blackColor];
    }
    return _progressHUD;
}

@end
